package com.project.frba.bifront.client.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.user.client.rpc.IsSerializable;

public class Cube implements IsSerializable{
	
	private List<CubeDataRow> dataRows = new ArrayList<CubeDataRow>();
	private Map<String, List<String>> allPropertyValues= new HashMap<String, List<String>>();
	private DataTree rowTree;
	private DataTree colTree;
	private String sql;
	
	
	public Cube(List<String> propertyNames) {
		this.addPropertyList(propertyNames);
	}
	
	public String getSql() {
		return sql;
	}

	public void setSql(String sql) {
		this.sql = sql;
	}

	public Cube(){
		
	}
	
	public List<String> getValuesForProperty(String propertyName){
		return this.allPropertyValues.get(propertyName);
	}
	
	public void addPropertyList(List<String> propertyNames){
		for (String propertyName : propertyNames) {
			this.allPropertyValues.put(propertyName, new ArrayList<String>());
		}
	}
	
	public void addDataRow(CubeDataRow dataRow){
		this.dataRows.add(dataRow);
		for (String propertyName : allPropertyValues.keySet()) {
			this.addPropertyValue(propertyName, dataRow.getValue(propertyName));
		}
	}
	
	public void addAllDataRows(List<CubeDataRow> dataRows){
		for (CubeDataRow row : dataRows) {
			this.addDataRow(row);
		}
	}
	
	private void addPropertyValue(String propertyName, String value){
		List<String> propertyValues = this.allPropertyValues.get(propertyName);
		if(!propertyValues.contains(value)){
			propertyValues.add(value);
		}
	}
	
	public Integer getAmount(List<String> properties){
		return this.getAmount(properties, null, null); 
	}
	
	private Integer getAmount(List<String> properties, String parent, String parentValue){
		Integer amount = 0;
		if((properties.size() == 1) && (parent != null) ){
			List<String> visited = new ArrayList<String>();
			String propertyName = properties.get(0);
			for (CubeDataRow dataRow : this.dataRows) {
				if(dataRow.isFromParent(parent, parentValue)){
					String value = dataRow.getValue(propertyName);
					if(!visited.contains(value)){
						amount++;
						visited.add(value);
					}
				}
			}
		}
		
		if( (properties.size() == 1) && (parent == null) ){
			String propertyName = properties.get(0);
			amount = this.allPropertyValues.get(propertyName).size();
		}
		
		
				
		if(properties.size() > 1){
			String propertyName = properties.get(0);
			for (String propertyValue : this.allPropertyValues.get(propertyName)) {
				amount = amount + this.getAmount(this.getTailList(properties, 1), propertyName, propertyValue);
			}
		}
		
		
		return amount;
	}
	
	public List<String> getTailList(List<String> list, Integer start){
		List<String> tail = new ArrayList<String>();
		for (int i = start; i < list.size(); i++) {
			tail.add(list.get(i));
		}
		
		return tail;
	}
	
	public Integer getAmountChildValues(String property, String propertyValue, String childPropertyName){
		List<String> values = new ArrayList<String>();
		for (CubeDataRow cubeRow : this.dataRows) {
			if(cubeRow.getValue(property).equals(propertyValue)){
				String childValue = cubeRow.getValue(childPropertyName);
				if(!values.contains(childValue)){
					values.add(childValue);
				}
			}
		}
		
		return values.size();
	}
	
	public List<CubeDataRow> getRows(){
		return this.dataRows;
	}

	public int getSize() {
		return this.dataRows.size();
	}
	
	public CubePosition getPosition(Integer i, DataTree rowTree, DataTree colTree) {
		CubeDataRow rowVO = this.dataRows.get(i);
		Integer rowIndex = rowTree.getIndexOfRow(rowVO);
		if(rowIndex == -1){
			rowIndex = colTree.getProperties().length;
		}
		Integer colIndex = colTree.getIndexOfRow(rowVO);
		if (colIndex == -1) {
			colIndex = rowTree.getProperties().length;
		}
		
		
		CubePosition position = new CubePosition(rowIndex, colIndex);
		
		return position;
	}

	public String getData(int i) {
		return this.dataRows.get(i).getData();
	}
	
	public void buildColumnTree(List<String> properties){
		this.colTree = this.buildTree(properties);
	}
	
	public void buildRowTree(List<String> properties){
		this.rowTree = this.buildTree(properties);
	}
	
	private DataTree buildTree(List<String> properties){
		return new DataTree(properties.toArray(new String[] {}), this);
	}
	
	public DataTree getColumnTree(){
		return this.colTree;
	}
	
	public DataTree getRowTree(){
		return this.rowTree;
	}
	
	public String getColumnLeafPropertyName(){
		return colTree.getLeafPropertyName();
	}
	
	public String getRowLeafPropertyName(){
		return rowTree.getLeafPropertyName();
	}
	
	public Collection<String> getProperties(){
		return allPropertyValues.keySet();
	}
	
	
	
	
	

}
